package com.slt.developkitweb.util;

import sun.misc.BASE64Decoder;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.security.Key;
import java.security.SecureRandom;
import java.util.Base64;


/**
 * 使用DES加密与解密
 */
public class DESUtils {

    /**
     * 解码
     */
    private final static Base64.Decoder DECODER = Base64.getDecoder();
    /**
     * 编码
     */
    private final static Base64.Encoder ENCODER = Base64.getEncoder();

    /**
     * 密钥算法
     */
    private static final String ALGORITHM2 = "DES";
    /**
     * 加密/解密算法-工作模式-填充模式
     */
    private static final String CIPHER_ALGORITHM2 = "DES/CBC/PKCS5Padding";
    /**
     * 默认编码
     */
    private static final String CHARSET2 = "utf-8";
    /**
     * 默认编码
     */
    private static final String ivParam = "87654321";
    /**
     * 默认编码
     */
    private static final String password = "123sdfsf";

    /**
     * 字符串加密，默认采用utf-8加密
     * @parameter strMing 需要加密的字符串
     * @parameter key 8位密钥
     * @parameter iv 初始向量即第二8位密钥
     */
    public static String encrypt(String strMing, String key){
        return encrypt(strMing, key,"utf-8");
    }

    /**
     * 字符串加密，默认采用utf-8加密,对应后台公共加密
     * @parameter strMing 需要加密的字符串
     * @parameter key 8位密钥
     * @parameter iv 初始向量即第二8位密钥
     */
    public static String encryptforConsole(String strMing, String key){
        return encryptforConsole(strMing, key,"utf-8");
    }

    /**
     * 字符串加密，默认采用utf-8加密
     * @parameter strMing 需要加密的字符串
     * @parameter key 8位密钥
     * @parameter iv 初始向量即第二8位密钥
     */
    public static String decrypt(String strMing, String key){
        return decrypt(strMing, key,"utf-8");
    }

    /**
     * 适配后台的字符串加密，默认采用utf-8加密
     * @parameter strMing 需要加密的字符串
     * @parameter key 8位密钥
     * @parameter iv 初始向量即第二8位密钥
     */
    public static String decryptForConsole(String strMing, String key){
        return decryptForConsole(strMing, key,"utf-8");
    }

    /**
     * 适配后台的字符串加密，默认采用utf-8加密
     * @parameter strMing 需要加密的字符串
     * @parameter key 8位密钥
     * @parameter iv 初始向量即第二8位密钥
     */
    public static String decryptParmForIdno(String strMing){
        return decryptForIdno(strMing);
    }

    /**
     * 字符串加密
     * @parameter strMing 需要加密的字符串
     * @parameter key 8位密钥
     * @parameter iv 初始向量即第二8位密钥
     * @parameter charset 编码方式
     */
    public static String encrypt(String strMing, String key, String charset){
        byte[] byteMi = null;
        byte[] byteMing = null;
        String strMi = "";
        try{

            byteMing = strMing.getBytes(charset);
            SecureRandom random = new SecureRandom();
            DESKeySpec desKey = new DESKeySpec(key.getBytes(charset));
            // 创建一个密匙工厂，然后用它把DESKeySpec转换成
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey securekey = keyFactory.generateSecret(desKey);
            // Cipher对象实际完成加密操作
            Cipher cipher = Cipher.getInstance("DES");
            // 用密匙初始化Cipher对象
            cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
            // 现在，获取数据并加密
            // 正式执行加密操作
            byteMi = cipher.doFinal(byteMing);
            strMi = ENCODER.encodeToString(byteMi);
        }catch(Exception e){
            throw new RuntimeException(e);
        }finally{
            byteMi = null;
        }
        return strMi;
    }

    /**
     * 加密，对应后台公共加密
     * @param strMing
     * @param key
     * @param charset
     * @return
     */
    public static String encryptforConsole(String strMing, String key, String charset){
        byte[] byteMi = null;
        byte[] byteMing = null;
        String strMi = "";
        try{

            byteMing = strMing.getBytes(charset);
            SecureRandom random = new SecureRandom();

            DESKeySpec desKey = new DESKeySpec(key.getBytes(charset));

            // 创建一个密匙工厂，然后用它把DESKeySpec转换成

            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");

            SecretKey securekey = keyFactory.generateSecret(desKey);

            // Cipher对象实际完成加密操作

            Cipher cipher = Cipher.getInstance("DES");

            // 用密匙初始化Cipher对象

            cipher.init(Cipher.ENCRYPT_MODE, securekey, random);

            // 现在，获取数据并加密

            // 正式执行加密操作

            byteMi = cipher.doFinal(byteMing);

            strMi = parseByte2HexStr(byteMi);

        }catch(Exception e){
            throw new RuntimeException(e);
        }finally{
            byteMi = null;
        }
        return strMi;
    }

    private static String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 字符串解密
     * @parameter strMi 解密串
     * @parameter key 密钥
     * @parameter charset 编码方式
     */
    public static String decrypt(String strMi, String key, String charset){
        byte[] byteMing = null;
        byte[] byteMi = null;
        String strMing = "";
        try{
            byteMi = DECODER.decode(strMi);
            // DES算法要求有一个可信任的随机数源
            SecureRandom random = new SecureRandom();
            // 创建一个DESKeySpec对象
            DESKeySpec desKey = new DESKeySpec(key.getBytes(charset));
            // 创建一个密匙工厂
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            // 将DESKeySpec对象转换成SecretKey对象
            SecretKey securekey = keyFactory.generateSecret(desKey);
            // Cipher对象实际完成解密操作
            Cipher cipher = Cipher.getInstance("DES");
            // 用密匙初始化Cipher对象
            cipher.init(Cipher.DECRYPT_MODE, securekey, random);
            // 真正开始解密操作
            byteMing = cipher.doFinal(byteMi);
            strMing = new String(byteMing, charset);
            return strMing;
        }catch(Exception e){
            throw new RuntimeException(e);
        }
    }


    /**
     * 适配后台的字符串解密
     * @parameter strMi 解密串
     * @parameter key 密钥
     * @parameter charset 编码方式
     */
    public static String decryptForConsole(String strMi, String key, String charset){
        byte[] byteMing = null;
        byte[] byteMi = null;
        String strMing = "";
        try{
            byteMi = parseHexStr2Byte(strMi);
            // DES算法要求有一个可信任的随机数源
            SecureRandom random = new SecureRandom();
            // 创建一个DESKeySpec对象
            DESKeySpec desKey = new DESKeySpec(key.getBytes(charset));
            // 创建一个密匙工厂
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            // 将DESKeySpec对象转换成SecretKey对象
            SecretKey securekey = keyFactory.generateSecret(desKey);
            // Cipher对象实际完成解密操作
            Cipher cipher = Cipher.getInstance("DES");
            // 用密匙初始化Cipher对象
            cipher.init(Cipher.DECRYPT_MODE, securekey, random);
            // 真正开始解密操作
            byteMing = cipher.doFinal(byteMi);
            strMing = new String(byteMing, charset);
            return strMing;
        }catch(Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * 适配后台的idno解密
     * @parameter strMi 解密串
     * @parameter key 密钥
     * @parameter charset 编码方式
     */
    public static String decryptForIdno(String data){
        if (password== null || password.length() < 8) {
            throw new RuntimeException("加密失败，key不能小于8位");
        }
        if (data == null){
            return null;
        }
        try {
            DESKeySpec dks = new DESKeySpec(password.getBytes(CHARSET2));
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM2);
            Key secretKey = keyFactory.generateSecret(dks);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM2);
            IvParameterSpec iv = new IvParameterSpec(ivParam.getBytes(CHARSET2));
            cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
            BASE64Decoder decoder = new BASE64Decoder();
            return new String(cipher.doFinal(decoder.decodeBuffer(data)), CHARSET2);
        } catch (Exception e) {
            e.printStackTrace();
            return data;
        }
    }

    /**
     * 将16进制转换为二进制
     *
     * @param hexStr
     * @return
     */
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2),
                    16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }
}
